home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / lists / mint / l_1199 / 831 < prev    next >
Encoding:
Internet Message Format  |  1994-08-27  |  4.7 KB

  1. From: roemer@informatik.uni-frankfurt.de
  2. Posted-Date: Mon, 17 Jan 94 15:52:26 "MET
  3. Received-Date: Mon, 17 Jan 94 15:52:26 +0100
  4. Message-Id: <9401171452.AA01122@diomedes.rbi.informatik.uni-frankfurt.de>
  5. Subject: MINTOS: Porting Library !?
  6. To: mint@atari.archive.umich.edu
  7. Date: Mon, 17 Jan 94 15:52:26 "MET
  8. Mailer: Elm [revision: 70.85]
  9.  
  10. Micheal Hohmuth writes:
  11.  
  12. > Rather, we should concentrate on things that have to be generalized
  13. > in order to reach a state where Unix software con be compiled out of
  14. > the box.
  15.  
  16. Yes, I would love that state, too. But obviously there are some problems,
  17. which cannot be solved transparently in the library without changing the
  18. MiNT kernel. Probably everyone who ever ported unix software to MiNT came
  19. across those things.
  20.  
  21. I think we should try to find general solutions for those problems which
  22. require only minimal changes to the source code (ie no mayor rewrites).
  23. Any other opinions, I think not :-).
  24.  
  25. So I'm going to start a list of what I call 'elegant solutions' to some
  26. of the above problems. Probably there are lots of such 'workarounds' out
  27. there. It would be great to have a look at and collect them.
  28. Perhaps we could even build a nonstandart library containing useful code
  29. for porting unix software.
  30.  
  31. Here are my suggestions:
  32.  
  33. (1)    Mint's fork() blocks the parent until the child exec()'s or
  34.     exit()'s. This is a problem in constructs like:
  35.  
  36.         if (!fork()) exit();
  37.  
  38.     Here is a workaround, which uses tfork() and requires only
  39.     minimal changes to the source. Using tfork() directly often
  40.     requires restructuring of the source.
  41.  
  42. ------------------------ cut ----------------------------
  43. #include <unistd.h>
  44. #include <fcntl.h>
  45. #include <ioctl.h>
  46. #include <setjmp.h>
  47. #include <signal.h>
  48.  
  49. static int fd_flags[32];
  50. static jmp_buf jmpbuf;
  51. static long sigmask;
  52. static struct sigaction sigacts[32];
  53.  
  54. int
  55. child_proc (long pip)
  56. {
  57.     char buf;
  58.     int i;
  59.  
  60.     sigsetmask (~0L);
  61.     if (read (pip, &buf, 1)) exit (0);
  62.     close (pip);
  63.     for (i = 0; i < 32; ++i) {
  64.         if (fd_flags[i] >= 0)
  65.             fcntl (i, F_SETFD, fd_flags[i]);
  66.     }
  67.     for (i = 0; i < 32; ++i) {
  68.         sigaction (i, &sigacts[i], 0);
  69.     }
  70.     longjmp (jmpbuf, 1);
  71. }
  72.     
  73. int
  74. __fork_and_exit (void)
  75. {
  76.     int i, pip[2];
  77.  
  78.     sigmask = sigsetmask (~0L);
  79.     if (pipe (pip) < 0) return -1;
  80.     for (i = 0; i < 32; ++i) {
  81.         fd_flags[i] = fcntl (i, F_GETFD, 0);
  82.         fcntl (i, F_SETFD, i == pip[1] ? FD_CLOEXEC : 0);
  83.     }
  84.     for (i = 0; i < 32; ++i) {
  85.         sigaction (i, 0, &sigacts[i]);
  86.     }
  87.     if (!setjmp (jmpbuf)) {
  88.         /* parent */
  89.         tfork (child_proc, pip[0]);
  90.         exit (0);
  91.     }
  92.     /* child */
  93.     sigsetmask (sigmask);
  94.     return 0;
  95. }
  96. --------------------------- cut ----------------------------
  97.  
  98.     __fork_and_exit() preserves file handles, signal handlers
  99.     and the set of masked signals to the child, much like fork()
  100.     does.
  101.     Its functionlity is the same as for if (!fork()) exit().
  102.     
  103. (2)    Another problem is that Mint/MintLibs read()/write() have
  104.     no POSIX nonblocking mode (activated with the O_NONBLOCK
  105.     fcntl()) flags. The difference to O_NDELAY nonblocking mode
  106.     is that read()/write() return -1 and EWOULDBLOCK/EAGAIN in
  107.     errno if no data/space is available at all (instead of
  108.     returning 0 when O_NDELAY is actice).
  109.     I know Entropy worked on this, but in the MintLibs this stuff
  110.     is commented out.
  111.     My solution is probably not more than a hack. Improvements
  112.     are appreciated.
  113.  
  114. -------------------------- cut -------------------------------
  115. #include <fcntl.h>
  116. #include <errno.h>
  117. #include <ioctl.h>
  118. #include <osbind.h>
  119. #include <mintbind.h>
  120.  
  121. #define UNLIMITED    1000000000L
  122.  
  123. int
  124. __posixish_read (int fd, void *buffer, unsigned int buflen)
  125. {
  126.     int r, s;
  127.     unsigned long buf;
  128.     extern int errno;
  129.  
  130.     r = Fread (fd, buflen, buffer);
  131.     if (r <= 0) {
  132.         if (r < 0) {
  133.             errno = -r;
  134.             return -1;
  135.         }
  136.         if (buflen && Fcntl (fd, 0, F_GETFL) & O_NDELAY) {
  137.             s = Fcntl (fd, &buf, FIONREAD);
  138.             if (!s && buf < UNLIMITED) {
  139.                 errno = EWOULDBLOCK;
  140.                 return -1;
  141.             }
  142.         }
  143.     }
  144.     return r;
  145. }
  146.  
  147. int
  148. __posixish_write (int fd, void *buffer, unsigned int buflen)
  149. {
  150.     int r, s;
  151.     unsigned long buf;
  152.     extern int errno;
  153.  
  154.     r = Fwrite (fd, buflen, buffer);
  155.     if (r <= 0) {
  156.         if (r < 0) {
  157.             errno = -r;
  158.             return -1;
  159.         }
  160.         if (buflen && Fcntl (fd, 0, F_GETFL) & O_NDELAY) {
  161.             s = Fcntl (fd, &buf, FIONWRITE);
  162.             if (!s && buf < UNLIMITED) {
  163.                 errno = EWOULDBLOCK;
  164.                 return -1;
  165.             }
  166.         }
  167.     }
  168.     return r;
  169. }
  170.  
  171. ------------------------- cut -----------------------------------
  172.  
  173.     When only O_NONBLOCK nonblocking mode is used, you could
  174.     then
  175.     #define read(a,b,c)    __posixish_read(a,b,c)
  176.     #define write(a,b,c)    __posixish_write(a,b,c)
  177.     #define O_NONBLOCK    O_NDELAY
  178.     and use this as a reasonabe emulation.
  179.     
  180. (3)    select()ing for exceptional conditions does not work.
  181.     This is a pitty for sockets (TCP) and out of band data.
  182.     Perhaps we could do a workaround using SIGURG.
  183.     Any suggestions?
  184.  
  185. Waiting for your opinion and suggestions,
  186. Kay.
  187.